package view;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.BevelBorder;
import javax.swing.JButton;

import control.Application;
import control.MatrixOperations;

import model.Observations;
import model.PAppRect;
import model.PathOptions;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.ButtonGroup;
import javax.swing.JRadioButton;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;

public class AppWindow extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1262030370190587259L;
	private int windowWidth = 800;
	private int windowHeight = 600;
	private CanvasPApplet canvas;
	private JPanel contentPane = new JPanel();
	private JPanel panel = new JPanel();
	private JButton btnPath = new JButton("Calculate Path");
	private JButton btnResetGrid = new JButton("Reset Grid");
	private final ButtonGroup buttonGroup = new ButtonGroup();
	private JRadioButton rdbtnGrass = new JRadioButton("Really Tall Grass");
	private JRadioButton rdbtnRocks = new JRadioButton("Rocks");
	private JRadioButton rdbtnNormalPath = new JRadioButton("Normal Path");
	private JRadioButton rdbtnExit = new JRadioButton("Exit");
	private JRadioButton rdbtnPlayer = new JRadioButton("Player");
	private Application instance = Application.getInstance();

	/**
	 * Create the frame.
	 */
	public AppWindow() {
		//se inicializan las variables basicas de la ventana		
		setTitle("hmm-maze-solver");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, windowWidth, windowHeight);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);		

		panel.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
		panel.setBounds(3*windowWidth/4, 0, 190, 571);
		contentPane.add(panel);
		panel.setLayout(null);
		
		btnResetGrid.setBounds(10, 11, 170, 49);
		panel.add(btnResetGrid);
		//se pregunta el tamaño de la matriz del laberinto...
		int pathMatrixSize=instance.getPathMatrixSize();
		//...para inicializar el canvas donde usamos processing
		canvas = new CanvasPApplet(3*windowWidth/4, windowHeight - 29,pathMatrixSize);
		canvas.init();
		contentPane.add(canvas);
		//se agrega el listener del boton reset grid
		btnResetGrid.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				canvas.resetGrid();
			}
		});
		//se agrega el listener del boton calculate path
		btnPath.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				MatrixOperations operations = new  MatrixOperations();
				operations.calculateTranProbabilities(instance.getTranMatrix(),canvas.getGrid());
				operations.calculateEmiProbabilities(instance.getEmiMatrix(), canvas.getGrid());
				
				Observations[] inputObs = new Observations[instance.getPathNodesCounter()+1];
				Arrays.fill(inputObs, Observations.PREFERENCE);
				
				System.out.println("Observations");
				for(Observations obs:inputObs){
					System.out.print(obs.name());
				}
				System.out.println();
				
				int playerIndex = canvas.getGrid().getPlayerIndex();
				double[] startProb = new double[instance.getPathMatrixSize()*instance.getPathMatrixSize()];		
				System.out.println(startProb.length);
				try{					
					startProb[playerIndex]=1;
				}catch(Exception e){
					System.out.println("Problem with the player index");
					return;
				}
				System.out.println("Start Probabilities");
				for(int i=0;i<startProb.length;i++){
					System.out.print(startProb[i]+" ");
				}
				System.out.println();
				Application.getInstance().getViterbi().viterbi(	inputObs, 
																												canvas.getGrid(), 
																												startProb, 
																												instance.getTranMatrix().getMatrix(), 
																												instance.getEmiMatrix().getMatrix(),
																												playerIndex);
				printObservations();
			}
		});
		btnPath.setBounds(10, 71, 170, 49);
		panel.add(btnPath);
		//se agrega el listener de la opcion Grass		
		rdbtnGrass.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				canvas.setActiveOption(PathOptions.GRASS);
			}
		});
		buttonGroup.add(rdbtnGrass);
		rdbtnGrass.setBounds(6, 449, 174, 23);
		panel.add(rdbtnGrass);
		//se agrega el listener de la opcion Rocks		
		rdbtnRocks.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				canvas.setActiveOption(PathOptions.ROCKS);
			}
		});
		buttonGroup.add(rdbtnRocks);
		rdbtnRocks.setBounds(6, 476, 174, 23);
		panel.add(rdbtnRocks);
		//se agrega el listener de la opcion Normal Path
		rdbtnNormalPath.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				canvas.setActiveOption(PathOptions.NORMAL);
			}
		});
		buttonGroup.add(rdbtnNormalPath);
		rdbtnNormalPath.setBounds(6, 422, 174, 23);
		rdbtnNormalPath.setSelected(true);
		panel.add(rdbtnNormalPath);
		buttonGroup.add(rdbtnExit);
		//se agrega el listener de la opcion Exit
		rdbtnExit.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				canvas.setActiveOption(PathOptions.EXIT);
			}
		});
		rdbtnExit.setBounds(6, 501, 149, 23);
		panel.add(rdbtnExit);
		buttonGroup.add(rdbtnPlayer);
		//se agrega el listener de la opcion player
		rdbtnPlayer.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				canvas.setActiveOption(PathOptions.PLAYER);		
			}
		});
		rdbtnPlayer.setBounds(6, 528, 149, 23);
		panel.add(rdbtnPlayer);
		//se centra en la pantalla con relative to null
		setLocationRelativeTo(null);
	}
	private void printObservations(){
		for (PAppRect[] row:canvas.getGrid().getSquareGrid()) {
      //for each number in the row
      for (PAppRect rect : row) {
      	System.out.print(rect.getActiveOption().name()+"\t");
      }
      System.out.println();
	  }
	}
}
